package cc.shacocloud.mirage.restful.bind.support;

import cc.shacocloud.mirage.restful.HttpRequest;
import cc.shacocloud.mirage.restful.HttpResponse;
import cc.shacocloud.mirage.restful.VertxInvokeHandler;
import cc.shacocloud.mirage.restful.http.MediaType;
import cc.shacocloud.mirage.utils.comparator.Order;
import cc.shacocloud.mirage.utils.comparator.Ordered;
import io.vertx.core.Future;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.json.Json;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.templ.freemarker.FreeMarkerTemplateEngine;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;

/**
 * 基于 {@code FreeMarker} 模板的异常处理器，将系统异常输出为 {@code html} 界面
 * <p>
 * 该异常解析处理器是系统的保底处理器，即如果没有其他处理器处理则都由这个处理器处理
 *
 * @see <a href="https://freemarker.apache.org/">文档</a>
 */
@Order
@Slf4j
public class FreeMarkerTemplateHandlerExceptionResolver extends AbstractDefaultHandlerExceptionResolver {
    
    public static final String DEFAULT_TEMPLATE_FILE_NAME = "mirage_error.ftl";
    private final FreeMarkerTemplateEngine freeMarkerTemplateEngine;
    
    public FreeMarkerTemplateHandlerExceptionResolver(FreeMarkerTemplateEngine freeMarkerTemplateEngine) {
        this.freeMarkerTemplateEngine = freeMarkerTemplateEngine;
        
    }
    
    @Override
    protected Future<Buffer> doResolveException(@NotNull HttpRequest request,
                                                @NotNull HttpResponse response,
                                                @NotNull VertxInvokeHandler handler,
                                                @NotNull Throwable cause,
                                                @NotNull DefaultExceptionMo defaultExceptionMo) {
        response.headers().setContentType(MediaType.TEXT_HTML);
        
        JsonObject params = new JsonObject(Json.encode(defaultExceptionMo));
        return this.freeMarkerTemplateEngine.render(params, DEFAULT_TEMPLATE_FILE_NAME);
    }
    
    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}
